#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
// #include <QMetaObject>
#include <QLabel>
#include <QTimer>
#include <QMetaEnum>

#include "videosettingsdialog.h"
#include "audiosettingsdialog.h"
#include "inputsettingsdialog.h"
#include "logdialog.h"

#include "NES.h"
#include "AudioOutput.h"
#include "GamePadInput.h"

#include "NES_InputMapper.h"




QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE




class MainWindow:public QMainWindow{
    Q_OBJECT

  public:
    NES* nes;
    AudioOutput* audioOutput;
    GamePadInput* gamePadInput;

    NES_InputMapper* nes_InputMapper;


    enum class InputDeviceIndex:int{
      Keyboard = 0,
      GamePad0 = 1,
      GamePad1 = 2
    };
    
    static QString ButtonToString(InputDeviceIndex Index,uint32_t Button);




    void LoadSettings();
    
    void SetDisplayMult(int Mult);
    int GetDisplayMult();

    void SetTVStandards(int TVStandards);
    int GetTVStandards();
    
    void SetVblankNMI_Delay(int VblankNMI_Delay);
    int GetVblankNMI_Delay();

    void SetMMC3_CountDelay(int MMC3_CountDelay);
    int GetMMC3_CountDelay();

    void SetSampleRate(H_NES_CPP::SampleRate SampleRate);
    H_NES_CPP::SampleRate GetSampleRate();

    void SetNumOfSampleBit(int NumOfSampleBit);
    int GetNumOfSampleBit();

    void SetPulseLR_Diff(int PulseLR_Diff);
    int GetPulseLR_Diff();

    void SetAudioFormat(H_NES_CPP::SampleRate SampleRate,int NumOfSampleBit);
    
    void NES_InputPress(InputDeviceIndex Index,uint32_t Button);
    void NES_InputRelease(InputDeviceIndex Index,uint32_t Button);

    void VideoSettingsDialogCloseEvent();
    void AudioSettingsDialogCloseEvent();
    void InputSettingsDialogCloseEvent();
    void LogDialogCloseEvent();




    uint32_t GetPadStatus();
    Q_INVOKABLE void DisplayNESFrame(void* Bitmap);
    Q_INVOKABLE void AudioDeviceError(QString Error);

    MainWindow(QWidget* parent = nullptr);
    ~MainWindow();

  protected:
    void closeEvent(QCloseEvent* event);
    void dragEnterEvent(QDragEnterEvent* event);
    void dropEvent(QDropEvent* event);

    void keyPressEvent(QKeyEvent* event);
    void keyReleaseEvent(QKeyEvent* event);

  private slots:

    void on_actionInfo_triggered();

    void on_actionOpenGLVersion_triggered();

    void on_actionOpen_triggered();

    void on_actionClose_triggered();

    void on_actionReset_triggered();

    void on_actionPower_triggered();

    void on_actionVideoSettings_triggered();

    void on_actionAudioSettings_triggered();

    void on_actionInputSettings_triggered();

    void on_actionH_NES_Output_triggered();

    void on_actionQuickSave_triggered();

    void on_actionQuickLoad_triggered();

    void on_actionSaveSlot0_triggered();

    void on_actionSaveSlot1_triggered();

    void on_actionSaveSlot2_triggered();

    void on_actionSaveSlot3_triggered();
    
    void on_actionLoadSlot0_triggered();

    void on_actionLoadSlot1_triggered();

    void on_actionLoadSlot2_triggered();

    void on_actionLoadSlot3_triggered();

    void on_actionSave_triggered();

    void on_actionLoad_triggered();

  private:
    Ui::MainWindow *ui;
    QLabel* StatusLabel;
    VideoSettingsDialog* videoSettingsDialog;
    AudioSettingsDialog* audioSettingsDialog;
    InputSettingsDialog* inputSettingsDialog;
    LogDialog* logDialog;
    QTimer* timerFPS;
    QTimer* timerPad;
    QTimer* timerLog;
    uint32_t ButtonStatus0;
    uint32_t ButtonStatus1;
    int FrameCount;

    int displayMult;

    bool NES_IsRun;
    unsigned char* rom;
    QString Path;

    int TVStandards;
    int VblankNMI_Delay;
    int MMC3_CountDelay;
    H_NES_CPP::SampleRate SampleRate;
    int NumOfSampleBit;
    int PulseLR_Diff;


    void Start(QString& Path);
    void Stop();
    QString ProgressFileName(QString Tag);
    void SaveProgress(QString Path);
    void LoadProgress(QString Path);
    void UI_IsRun(bool IsRun);
    void PadPressEvent(int Index,uint32_t Button);
    void PadReleaseEvent(int Index,uint32_t Button);

    void TimerFPS_Callback();
    void TimerPad_Callback();
    void TimerLog_Callback();


    
    static QMetaEnum metaKey;

};
#endif // MAINWINDOW_H
